import type {Func, Nullable, Recordable} from "../types";
import {isArray, isFunction, isNullOrUnDef} from "./assert";

/**
 * 根据key将数组转成对象
 * @param arr
 * @param key
 * @param callback
 */
export const listToMapForSingle = <T extends Recordable>(arr: T[], key: string | Func, callback: Nullable<Func> = null) => {
    const _map: Recordable = {};
    for (let i = 0, len = arr.length; i < len; i++) {
        let item = arr[i];
        let result = isFunction(callback) ? callback(item) : item;
        let _key: string = isFunction(key) ? key(item) : item[key];
        _map[_key] = result;
    }
    return _map;
};

/**
 * 根据key将数组转成对象，且一个key可能存在多个对象匹配
 * @param arr
 * @param key
 */
export const listToMap = <T extends Recordable>(arr: T[], key: string | Func) => {
    const _map: Recordable = {};
    for (let item of arr) {
        let _key = isFunction(key) ? key(item) : item[key];
        _map[_key] = _map[_key] ? ([] as Recordable[]).concat(_map[_key]).concat(item) : [item]
    }
    return _map;
}

/**
 * 将参数转成数组
 * @param value
 */
export const toArray = <T = any>(value: T): T | T[] => {
    return isArray(value) ? value : (!isNullOrUnDef(value) ? [value] : []);
};

/**
 * 扁平化二维数组
 * @param arr
 */
export const arrayFlat2 = <T = any>(arr: T[][]): T[] => {
    return arr.flat()
};

/**
 * 数组根据指定key去重
 * @param array
 * @param key
 */
export const removeDuplicates = <T, K extends keyof T>(array: T[], key: K): T[] => {
    const seen = new Set<T[K]>();
    return array.filter((item) => {
        const value = item[key];
        if (!seen.has(value)) {
            seen.add(value);
            return true;
        }
        return false;
    });
};